package postgres

import (
	"context"
	"fmt"
	"go.uber.org/zap"
	"gorm.io/gorm"
	logger "pay/collector/logger"
	"pay/config"
	"pay/errors"
	"pay/model"
	"pay/model/entity"
	"pay/utils"
)

var FeePlanPaymentOrder = &feePlanPaymentOrder{}

type feePlanPaymentOrder struct{}

func init() {
	Register(FeePlanPaymentOrder)
}

func (a *feePlanPaymentOrder) Init() {
	if config.Conf.AutoMigrate {
		p := &entity.FeePlanPaymentOrder{}
		if db.Migrator().HasTable(p) {
			logger.Debug("table already exist: ", zap.String("table", p.TableName()))
			return
		}
		if err := db.AutoMigrate(p); err != nil {
			logger.Error("filed to create table please check config or manually create", zap.String("table", p.TableName()), zap.String("err", err.Error()))
		} else {
			logger.Info("create table successfully", zap.String("table", p.TableName()))
		}
	}
}

// Create
func (a *feePlanPaymentOrder) Create(ctx context.Context, m *entity.FeePlanPaymentOrder) (int64, error) {
	err := GetDB(ctx).Create(m).Error
	return m.Id, err
}

// Find detail
func (a *feePlanPaymentOrder) Find(ctx context.Context, in *model.FeePlanPaymentOrderInfoRequest) (*entity.FeePlanPaymentOrder, error) {
	e := &entity.FeePlanPaymentOrder{}

	q := GetDB(ctx).Model(&entity.FeePlanPaymentOrder{})

	if in.Id == 0 {
		return e, errors.New("condition illegal")
	}
	err := q.First(&e, in.Id).Error
	return e, err
}

// Update
func (a *feePlanPaymentOrder) Update(ctx context.Context, id int64, dict map[string]interface{}) error {
	return GetDB(ctx).Model(&entity.FeePlanPaymentOrder{}).Where("id = ?", id).Updates(dict).Error
}

// Delete
func (a *feePlanPaymentOrder) Delete(ctx context.Context, id int64) error {
	return GetDB(ctx).Delete(&entity.FeePlanPaymentOrder{}, id).Error
}

// List query list
func (a *feePlanPaymentOrder) List(ctx context.Context, in *model.FeePlanPaymentOrderListRequest, opts ...model.QueryOptions) (int, []*entity.FeePlanPaymentOrder, error) {

	var (
		opt                  = model.GetQueryOption(opts...)
		q                    = GetDB(ctx).Model(&entity.FeePlanPaymentOrder{})
		err                  error
		total                int64
		feePlanPaymentOrders []*entity.FeePlanPaymentOrder
	)

	if in.Id != nil {

		q = q.Where("id = ?", in.Id)

	}

	if in.TradeNo != nil {

		q = q.Where("trade_no = ?", in.TradeNo)

	}

	if in.UserId != nil {

		q = q.Where("user_id = ?", in.UserId)

	}

	if in.UserName != nil {

		q = q.Where("user_name = ?", in.UserName)

	}

	if in.UserPhone != nil {

		q = q.Where("user_phone = ?", in.UserPhone)

	}

	if in.EbikeId != nil {

		q = q.Where("ebike_id = ?", in.EbikeId)

	}

	if in.EbikeName != nil {

		q = q.Where("ebike_name = ?", in.EbikeName)

	}

	if in.EbikeSnCode != nil {

		q = q.Where("ebike_sn_code = ?", in.EbikeSnCode)

	}

	if in.EbikeTypeId != nil {

		q = q.Where("ebike_type_id = ?", in.EbikeTypeId)

	}

	if in.EbikeTypeName != nil {

		q = q.Where("ebike_type_name = ?", in.EbikeTypeName)

	}

	if in.Status != nil {

		q = q.Where("status = ?", in.Status)

	}

	if in.Description != nil {

		q = q.Where("description like ?", utils.SqlLike(in.Description))

	}

	if in.FeePlanId != nil {

		q = q.Where("fee_plan_id = ?", in.FeePlanId)

	}

	if in.FeePlanGroupId != nil {

		q = q.Where("fee_plan_group_id = ?", in.FeePlanGroupId)

	}

	if in.FeePlanPackNo != nil {

		q = q.Where("fee_plan_pack_no = ?", in.FeePlanPackNo)

	}

	if in.Money != nil {

		q = q.Where("money = ?", in.Money)

	}

	if in.CallBackCnt != nil {

		q = q.Where("call_back_cnt = ?", in.CallBackCnt)

	}

	if in.Channel != nil {

		q = q.Where("channel = ?", in.Channel)

	}

	if in.TransactionId != nil {

		q = q.Where("transaction_id = ?", in.TransactionId)

	}

	if in.CreatedAt != nil {

		q = q.Where("created_at = ?", in.CreatedAt)

	}

	if in.UpdatedAt != nil {

		q = q.Where("updated_at = ?", in.UpdatedAt)

	}

	if len(opt.SelectFields) > 0 {
		q = q.Select(opt.SelectFields)
	}

	if len(opt.OrderFields) > 0 {
		q = q.Order(fmt.Sprintf("%v", model.ParseOrder(opt.OrderFields)))
	}

	b := !opt.OnlyCount && !opt.OnlyList
	if opt.OnlyCount || b {
		if err = q.Count(&total).Error; err != nil {
			return 0, nil, err
		}
	}

	if opt.OnlyList || b {
		if err = q.Limit(in.Size).Offset((in.Index - 1) * in.Size).Find(&feePlanPaymentOrders).Error; err != nil {
			return 0, nil, err
		}
	}
	return int(total), feePlanPaymentOrders, nil
}

// ExecTransaction execute database transaction
func (a *feePlanPaymentOrder) ExecTransaction(ctx context.Context, callback func(ctx context.Context) error) error {
	return GetDB(ctx).Transaction(func(tx *gorm.DB) error {
		ctx = context.WithValue(ctx, ContextTxKey, tx)
		return callback(ctx)
	})
}
